import { ref, onMounted, onUnmounted, readonly, type Ref } from 'vue'

export interface TouchPoint {
  x: number
  y: number
  time: number
}

export interface SwipeDirection {
  horizontal: 'left' | 'right' | null
  vertical: 'up' | 'down' | null
}

export interface TouchOptions {
  threshold?: number          // 滑动阈值(px)
  timeout?: number           // 长按时间(ms)
  preventScroll?: boolean    // 是否阻止滚动
  capture?: boolean          // 是否使用捕获模式
}

export interface TouchEvents {
  onSwipe?: (direction: SwipeDirection, distance: { x: number; y: number }) => void
  onTap?: (point: TouchPoint) => void
  onDoubleTap?: (point: TouchPoint) => void
  onLongPress?: (point: TouchPoint) => void
  onPinch?: (scale: number, center: TouchPoint) => void
  onRotate?: (angle: number, center: TouchPoint) => void
}

/**
 * 触摸手势识别组合式函数
 */
export function useTouch(
  target: Ref<HTMLElement | null>,
  events: TouchEvents = {},
  options: TouchOptions = {}
) {
  const {
    threshold = 50,
    timeout = 500,
    preventScroll = false,
    capture = false
  } = options

  // 触摸状态
  const isPressed = ref(false)
  const isSwiping = ref(false)
  const isPinching = ref(false)
  
  // 触摸点记录
  const startPoint = ref<TouchPoint | null>(null)
  const currentPoint = ref<TouchPoint | null>(null)
  const lastTapTime = ref(0)
  
  // 多点触控
  const touches = ref<TouchPoint[]>([])
  const initialDistance = ref(0)
  const initialAngle = ref(0)
  
  // 定时器
  let longPressTimer: NodeJS.Timeout | null = null
  
  // 工具函数
  const getDistance = (p1: TouchPoint, p2: TouchPoint): number => {
    return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2))
  }
  
  const getAngle = (p1: TouchPoint, p2: TouchPoint): number => {
    return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI
  }
  
  const getCenter = (touches: TouchPoint[]): TouchPoint => {
    const x = touches.reduce((sum, touch) => sum + touch.x, 0) / touches.length
    const y = touches.reduce((sum, touch) => sum + touch.y, 0) / touches.length
    return { x, y, time: Date.now() }
  }
  
  const createTouchPoint = (touch: Touch): TouchPoint => ({
    x: touch.clientX,
    y: touch.clientY,
    time: Date.now()
  })
  
  const getSwipeDirection = (start: TouchPoint, end: TouchPoint): SwipeDirection => {
    const deltaX = end.x - start.x
    const deltaY = end.y - start.y
    
    return {
      horizontal: Math.abs(deltaX) > threshold 
        ? (deltaX > 0 ? 'right' : 'left') 
        : null,
      vertical: Math.abs(deltaY) > threshold 
        ? (deltaY > 0 ? 'down' : 'up') 
        : null
    }
  }

  // 触摸开始
  const handleTouchStart = (e: TouchEvent) => {
    if (preventScroll) {
      e.preventDefault()
    }
    
    const touch = e.touches[0]
    const point = createTouchPoint(touch)
    
    startPoint.value = point
    currentPoint.value = point
    isPressed.value = true
    isSwiping.value = false
    
    // 记录所有触摸点
    touches.value = Array.from(e.touches).map(createTouchPoint)
    
    // 多点触控初始状态
    if (e.touches.length === 2) {
      isPinching.value = true
      const [touch1, touch2] = touches.value
      initialDistance.value = getDistance(touch1, touch2)
      initialAngle.value = getAngle(touch1, touch2)
    }
    
    // 长按检测
    if (events.onLongPress) {
      longPressTimer = setTimeout(() => {
        if (isPressed.value && !isSwiping.value) {
          events.onLongPress!(point)
        }
      }, timeout)
    }
  }

  // 触摸移动
  const handleTouchMove = (e: TouchEvent) => {
    if (!isPressed.value) return
    
    if (preventScroll) {
      e.preventDefault()
    }
    
    const touch = e.touches[0]
    const point = createTouchPoint(touch)
    currentPoint.value = point
    
    // 更新触摸点
    touches.value = Array.from(e.touches).map(createTouchPoint)
    
    // 检测滑动
    if (startPoint.value) {
      const deltaX = Math.abs(point.x - startPoint.value.x)
      const deltaY = Math.abs(point.y - startPoint.value.y)
      
      if ((deltaX > threshold || deltaY > threshold) && !isSwiping.value) {
        isSwiping.value = true
        clearLongPressTimer()
      }
    }
    
    // 多点触控手势
    if (e.touches.length === 2 && isPinching.value) {
      const [touch1, touch2] = touches.value
      const currentDistance = getDistance(touch1, touch2)
      const currentAngle = getAngle(touch1, touch2)
      
      // 缩放手势
      if (events.onPinch && initialDistance.value > 0) {
        const scale = currentDistance / initialDistance.value
        const center = getCenter(touches.value)
        events.onPinch(scale, center)
      }
      
      // 旋转手势
      if (events.onRotate) {
        const angleDiff = currentAngle - initialAngle.value
        const center = getCenter(touches.value)
        events.onRotate(angleDiff, center)
      }
    }
  }

  // 触摸结束
  const handleTouchEnd = (e: TouchEvent) => {
    clearLongPressTimer()
    
    if (!isPressed.value) return
    
    const touch = e.changedTouches[0]
    const endPoint = createTouchPoint(touch)
    
    // 单点手势检测
    if (!isSwiping.value && startPoint.value) {
      const now = Date.now()
      const timeDiff = now - lastTapTime.value
      
      // 双击检测
      if (timeDiff < 300 && events.onDoubleTap) {
        events.onDoubleTap(endPoint)
        lastTapTime.value = 0
      } else {
        // 单击检测
        if (events.onTap) {
          setTimeout(() => {
            if (lastTapTime.value === now) {
              events.onTap!(endPoint)
            }
          }, 300)
        }
        lastTapTime.value = now
      }
    }
    
    // 滑动手势检测
    if (isSwiping.value && startPoint.value && events.onSwipe) {
      const direction = getSwipeDirection(startPoint.value, endPoint)
      const distance = {
        x: endPoint.x - startPoint.value.x,
        y: endPoint.y - startPoint.value.y
      }
      events.onSwipe(direction, distance)
    }
    
    // 重置状态
    isPressed.value = false
    isSwiping.value = false
    isPinching.value = false
    startPoint.value = null
    currentPoint.value = null
    touches.value = []
    initialDistance.value = 0
    initialAngle.value = 0
  }

  // 触摸取消
  const handleTouchCancel = () => {
    clearLongPressTimer()
    isPressed.value = false
    isSwiping.value = false
    isPinching.value = false
    startPoint.value = null
    currentPoint.value = null
  }

  const clearLongPressTimer = () => {
    if (longPressTimer) {
      clearTimeout(longPressTimer)
      longPressTimer = null
    }
  }

  // 生命周期管理
  onMounted(() => {
    const element = target.value
    if (!element) return
    
    const options = { passive: !preventScroll, capture }
    
    element.addEventListener('touchstart', handleTouchStart, options)
    element.addEventListener('touchmove', handleTouchMove, options)
    element.addEventListener('touchend', handleTouchEnd, options)
    element.addEventListener('touchcancel', handleTouchCancel, options)
  })

  onUnmounted(() => {
    const element = target.value
    if (!element) return
    
    clearLongPressTimer()
    
    element.removeEventListener('touchstart', handleTouchStart)
    element.removeEventListener('touchmove', handleTouchMove)
    element.removeEventListener('touchend', handleTouchEnd)
    element.removeEventListener('touchcancel', handleTouchCancel)
  })

  return {
    isPressed: readonly(isPressed),
    isSwiping: readonly(isSwiping),
    isPinching: readonly(isPinching),
    startPoint: readonly(startPoint),
    currentPoint: readonly(currentPoint),
    touches: readonly(touches)
  }
}

/**
 * 滑动手势专用函数
 */
export function useSwipe(
  target: Ref<HTMLElement | null>,
  onSwipe: (direction: SwipeDirection, distance: { x: number; y: number }) => void,
  options: TouchOptions = {}
) {
  return useTouch(target, { onSwipe }, options)
}

/**
 * 长按手势专用函数
 */
export function useLongPress(
  target: Ref<HTMLElement | null>,
  onLongPress: (point: TouchPoint) => void,
  options: TouchOptions = {}
) {
  return useTouch(target, { onLongPress }, options)
}

/**
 * 双击手势专用函数
 */
export function useDoubleTap(
  target: Ref<HTMLElement | null>,
  onDoubleTap: (point: TouchPoint) => void,
  options: TouchOptions = {}
) {
  return useTouch(target, { onDoubleTap }, options)
}

/**
 * 缩放手势专用函数
 */
export function usePinch(
  target: Ref<HTMLElement | null>,
  onPinch: (scale: number, center: TouchPoint) => void,
  options: TouchOptions = {}
) {
  return useTouch(target, { onPinch }, options)
}